﻿#include "OiPCH.hpp"
#include "PLScannerCore/Tools/OiPlyTool.hpp"
#include <QtCharts/QChart>
#include <QtCharts/QValueAxis>

namespace Oi
{
    using namespace PLScannerCore;

    namespace PLScannerDll
    {
        class ValueSplineView : public DynamicSplineView
        {
        public:
            ValueSplineView(const QStringList list, QWidget *parent = Q_NULLPTR);
            ~ValueSplineView();

        public:
            QMap<QString, QList<QPointF>> loadData(const QDateTime from, const QDateTime end);
            void addData(const qreal dt, QMap<QString, qreal> data);

        public:
            QStringList splineList;

//         public:
//             QList<QPointF> _values;

        };

        ValueSplineView::ValueSplineView(const QStringList list, QWidget *parent /*= Q_NULLPTR*/)
            : DynamicSplineView(list, parent)
        {
            splineList = list;
            //chart()->setFlashFitMode(DynamicSplineChart::FitToData);
            auto axis = qobject_cast<QtCharts::QValueAxis*>(chart()->axisY());
            axis->setLabelFormat("%.2f");
            axis->setTickCount(6);

            chart()->setXRange(2*60 * 60);
           // axis->setRange(0.0, 1.0);
        }

        ValueSplineView::~ValueSplineView()
        {

        }

        QMap<QString, QList<QPointF>> ValueSplineView::loadData(const QDateTime from, const QDateTime end)
        {
            QMap<QString, QList<QPointF>> datas;

            for (auto & key : splineList)
            {
                datas[key] = QList<QPointF>();
            }

            Database::instance()->queryFixedValues(splineList, datas, from, end);

            return datas;

        }

        void ValueSplineView::addData(const qreal dt, QMap<QString, qreal> data)
        {
            chart()->addValues(dt, data);
//             _values.push_back(QPointF(dt, data["厚度"]));
//             if (_values.size() > 1000)
//             {
//                 _values.pop_front();
//             }
        }

        class ValuePageImpl : public Impl<ValuePage>
        {
        public:
            void init();


        public:
            ValueSplineView* _spline;
//            ToolProfilesView* _profile;

            ValueLabel* _value;

            ValueLabel* _thicknessCp;

            ValueLabel* _thicknessCpk;

             QLineEdit* _setPos;
             QLineEdit* _curPos;
             QPushButton* _move;

            QTimer _timer;
            QList<double> _thicknessList;

            double _valueMax;
            double _valueMin;

        public:
            ProductParams _params;

        public:
            void updateCPCPK(const double value, const double width);
            void setValue(const double dt, const double value, const double width);
            void updateTol(ValueLabel* label, int index, QString key);
            void updateTol(ValueSplineView* view, int index, QString key);
            void updateTol(double& upper, double& lower, int index, QString key);
        };

        void ValuePageImpl::init()
        {
            OI_Q(ValuePage);

            QVBoxLayout* mainLayout = new QVBoxLayout(q);

            //_profile = new ToolProfilesView();

            //_profile->setPageFlag(PMP_FixedMeasure);

             QFormLayout* layout1 = new QFormLayout(q);

             _setPos = new QLineEdit();
             _curPos = new QLineEdit();
             _move = new QPushButton(ValuePage::tr("开始定位"));
             q->connect(_move, &QPushButton::clicked, q, &ValuePage::updateLocation);
             _value = new ValueLabel(q);
             _value->setText(ValuePage::tr("厚度"));
             _value->setPrecise(2);
             _value->setUnit("mm");
             _value->setCheckEnable(true);
             _value->setMinimumHeight(220);

             _thicknessCp = new ValueLabel(q);
             _thicknessCp->setText("CP");
             _thicknessCp->setPrecise(2);
             _thicknessCp->setUnit("");
             _thicknessCp->setCheckEnable(true);
             _thicknessCp->setEarlyLower(1.0);
             _thicknessCp->setLower(0.67);
             _thicknessCp->setUpper(MAX_LIMIT_VALUE);
             _thicknessCp->setMinimumHeight(220);
             _thicknessCpk = new ValueLabel(q);
             _thicknessCpk->setText("CPK");
             _thicknessCpk->setPrecise(2);
             _thicknessCpk->setUnit("");
             _thicknessCpk->setCheckEnable(true);
             _thicknessCpk->setEarlyLower(1.0);
             _thicknessCpk->setLower(0.67);
             _thicknessCpk->setUpper(MAX_LIMIT_VALUE);
             _thicknessCpk->setMinimumHeight(220);
             _setPos->setValidator(new QDoubleValidator());
             _curPos->setReadOnly(true);
             layout1->addRow(ValuePage::tr("定点位置"), _setPos);
             layout1->addRow(ValuePage::tr("当前位置"), _curPos);

             layout1->addWidget(_move);
            //layout1->addStretch();

            _spline = new ValueSplineView({ "厚度"});
            QGridLayout* blayout = new QGridLayout(q);
            blayout->addWidget(_value,          0, 0, 1, 1);
            blayout->addWidget(_thicknessCp,    0, 1, 1, 1);
            blayout->addWidget(_thicknessCpk,   0, 2, 1, 1);
            blayout->addWidget(_spline, 1, 0, 3, 3);
            mainLayout->addLayout(layout1, 0);
            mainLayout->addLayout(blayout, 1);
        }

        void ValuePageImpl::updateCPCPK(const double value, const double width)
        {
            _thicknessList.push_back(value);

            if (_thicknessList.size() > 100)
            {
                _thicknessList.pop_front();
            }

            if (_thicknessCp->isVisible() && _thicknessCpk->isVisible())
            {
                if (_thicknessList.size() < 10)
                {
                    _thicknessCp->setValue(0.0);
                    _thicknessCpk->setValue(0.0);
                }
                else
                {
                    double cp, cpk;
                    PLScannerUtil::calCPCPK(_thicknessList, cp, cpk, _valueMax, _valueMin);
                    _thicknessCp->setValue(cp);
                    _thicknessCpk->setValue(cpk);
                }
            }
        }

        void ValuePageImpl::setValue(const double dt, const double value, const double width)
        {
            _value->setValue(value);

            QMap<QString, double> vm;
            vm["厚度"] = value;
            _spline->addData(dt, vm);
        }

        void ValuePageImpl::updateTol(ValueLabel* label, int index, QString key)
        {
            int enable = 0;
            double warningTol = 0.0;
            double errorTol = 0.0;
            double stdValue = 0.0;
            return;
            if (_params.getMeasureEnable(index, key, enable) &&
                _params.getMeasureWarningTol(index, key, warningTol) &&
                _params.getMeasureErrorTol(index, key, errorTol) &&
                _params.getStdValue(index, key, stdValue))
            {
                label->setEnabled(true);
                if (enable & TC_WarningEnable)
                {
                    label->setEarlyUpper(stdValue + warningTol);
                    label->setEarlyLower(stdValue - warningTol);
                }

                if (enable & TC_ErrorEnable)
                {
                    label->setUpper(stdValue + errorTol);
                    label->setLower(stdValue - errorTol);
                }
            }
            else
            {
                label->setEnabled(false);
            }
        }

        void ValuePageImpl::updateTol(ValueSplineView* view, int index, QString key)
        {
            double errorTol = 0.0;
            double stdValue = 0.0;
            return;
            if (_params.getMeasureErrorTol(index, key, errorTol) &&
                _params.getStdValue(index, key, stdValue))
            {
                view->setLimit(stdValue + errorTol, stdValue - errorTol);
            }
        }

        void ValuePageImpl::updateTol(double& upper, double& lower, int index, QString key)
        {
            double errorTol = 0.0;
            double stdValue = 0.0;
            return;
            if (_params.getMeasureErrorTol(index, key, errorTol) &&
                _params.getStdValue(index, key, stdValue))
            {
                upper = stdValue + errorTol;
                lower = stdValue - errorTol;
            }
            else
            {
                upper = 0;
                lower = 0;
            }
        }


        ValuePage::ValuePage(QWidget * parent /*= nullptr*/)
            : PageAbstract(parent)
        {
            OI_I(ValuePage)->init();
        }

        void ValuePage::setParams(const PLScannerCore::ProductParams& params)
        {
            OI_F(ValuePage);
            if (d->_params == params)
            {
                return;
            }

            d->_params = params;
            d->_value->setStdValue(params.fixedPoint.y());
            d->_value->setEarlyUpper(params.fixedPoint.y() + PLScanner::instance()->thicknessWTDefault);
            d->_value->setEarlyLower(params.fixedPoint.y() - PLScanner::instance()->thicknessWTDefault);
            d->_value->setUpper(params.fixedPoint.y() + PLScanner::instance()->thicknessETDefault);
            d->_value->setLower(params.fixedPoint.y() - PLScanner::instance()->thicknessETDefault);
            
            //d->_profile->setParams(params);
            //d->_profile->zoomFit();
            d->_valueMax = params.fixedPoint.y() + PLScanner::instance()->thicknessETDefault;
            d->_valueMin = params.fixedPoint.y() - PLScanner::instance()->thicknessETDefault;

            d->_thicknessList.clear();
        }

        int ValuePage::setResult(const PLScannerCore::WorkResult::Result& result)
        {
            return 0;
        }

        void ValuePage::updateLocation()
        {
            OI_F(ValuePage);
            int pos = d->_setPos->text().toInt();
            Core::OiSettings()->setValue("Product/FixPos", pos);
            Core::OiSettings()->sync();
        }
        int ValuePage::setValue(const double value, const double width)
        {
            OI_F(ValuePage);

            int resultCode = WorkResult::RC_Success;

            if (value <= 0.1)
            {
                return resultCode;
            }
            auto dt = QDateTime::currentDateTime().toMSecsSinceEpoch();
            double stdVal = 0;
            double val = value;
            if (qAbs(d->_params.materialsThickness - value) < qAbs(d->_params.fixedPoint.y() - value))
            {
                stdVal = d->_params.materialsThickness;
            }
            else
            {
                stdVal = d->_params.fixedPoint.y();
            }
            if (qAbs(stdVal - value)<0.25)
            {
                val -= (value - stdVal) * 0.5;
            }
            d->setValue(dt, val, stdVal);
            d->updateCPCPK(val, stdVal);

            if (resultCode == WorkResult::RC_Success)
            {
                if (d->_value->status() == ValueLabel::LS_Error)
                {
                    resultCode = WorkResult::RC_Error;
                }
                else if (d->_value->status() == ValueLabel::LS_Warning)
                {
                    resultCode = WorkResult::RC_Warning;
                }
            }
            d->_curPos->setText(QString::number(Motor::instance()->axisPos()));
            FixedValueRow row;
            row.result = resultCode;
            row.datetime = QDateTime::currentDateTime();
            row.formula = d->_params.specName;
            row.user = UserManage::instance()->current();
            row.team = UserManage::instance()->team();
            row.value = value;
            row.stdValue = (d->_valueMax + d->_valueMin) / 2;
            row.errValue = (d->_valueMax - d->_valueMin) / 2;

            Database::instance()->insert(row);

            if (resultCode == WorkResult::RC_Success)
            {
                Motor::instance()->setResult(1);
            }
            else if (resultCode == WorkResult::RC_Warning)
            {
                Motor::instance()->setResult(0);
            }
            else
            {
                Motor::instance()->setResult(2);
            }

            auto outputSystem = Core::OiSettings()->value("System/OutputSystem").toString();

            if (outputSystem == "Linglong_Local_DB")
            {
                if (PLScannerOutput::saveToSys(row, outputSystem))
                {

                }
            }
            else if (outputSystem == "OPC")
            {
                if (PLScannerOutput::saveToSys(d->_params.specName, row.value, resultCode, outputSystem))
                {

                }
            }
            return resultCode;
        }

        void ValuePage::setRun(bool flag)
        {
            OI_F(ValuePage);
            d->_spline->run(flag);
        }

        void ValuePage::toCurrent()
        {
            OI_F(ValuePage);
            d->_spline->toCurrent();
        }

        void ValuePage::updatePermission()
        {
            OI_F(ValuePage);

            //d->_thicknessCp->setVisible(UserManage::instance()->permission() & PT_ViewStatistics);
            //d->_thicknessCpk->setVisible(UserManage::instance()->permission() & PT_ViewStatistics);
        }

        void ValuePage::update()
        {
            OI_F(ValuePage);
            d->_spline->update();
        }

        void ValuePage::resizeEvent(QResizeEvent *event)
        {
            OI_F(ValuePage);
 //           d->_profile->zoomFit();
        }

        void ValuePage::showEvent(QShowEvent *event)
        {
            OI_F(ValuePage);
//            d->_profile->zoomFit();
            toCurrent();
        }

    }
}